﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tetris
{
    enum FigurePosition
    {
        North,
        East,
        South,
        West
    }

    enum CurrentFigure
    {
        Cube,
        Piptik,
        Horse,
        Twos,
        Stick
    }

    class GameLogic
    {
        public GameField field;
        public Frame frame;
        public Drawer drw;
        Figures figure;
        CurrentFigure currentFigure;
        List<Node> figureList;
        List<Node> finishedList;
        ConsoleKeyInfo key = default(ConsoleKeyInfo);
        private readonly Handler hd;
        Random rnd;
        List<int> coordYCompleteLine;
        int score = 0;
        int currentPoints = 0;
        int completeLines = 0;
        int speed;
        //bool isGameOver = false;
        //bool isPaused = true;
        //bool isNewRound = false;

        public GameLogic(GameField field, Handler keyH)
        {
            this.field = field;
            frame = new Frame(this.field);
            drw = new Drawer();
            drw.FrameDrawer(this.field);
            currentFigure = new CurrentFigure();
            finishedList = new List<Node>();
            figureList = new List<Node>();
            speed = 300;
            List<int> coordYCompleteLine = new List<int>();
            rnd = new Random();
            hd = keyH;
            hd.KeyLeft += MoveFigureLeft;
            hd.KeyRight += MoveFigureRight;
            hd.KeyDown += MoveFigureDown;
            hd.KeyUp += RotateFigure;
        }

        public List<Node> NextFigureGeneration()
        {

            int a = rnd.Next(1, 6);
            switch (a)
            {
                case 1:
                    {
                        figure = new Cube(field);
                        currentFigure = CurrentFigure.Cube;
                        break;
                    }
                case 2:
                    {
                        figure = new Piptik(field);
                        currentFigure = CurrentFigure.Piptik;
                        break;
                    }
                case 3:
                    {
                        figure = new Horse(field);
                        currentFigure = CurrentFigure.Horse;
                        break;
                    }
                case 4:
                    {
                        figure = new Twos(field);
                        currentFigure = CurrentFigure.Twos;
                        break;
                    }
                case 5:
                    {
                        figure = new Stick(field);
                        currentFigure = CurrentFigure.Stick;
                        break;
                    }
                default:
                    break;
            }
            return new List<Node>()
            { figure.Node1,
                figure.Node2,
                figure.Node3,
                figure.Node4
            };
        }

        private void MoveFigureLeft(object sender, EventArgs e)
        {
            if (!Validation.IsOnLeft(field, figureList) && !Validation.IsOnFinishedListLeftSideMoving(figureList, finishedList))
            {
                figure.MoveFigureLeft();
            }
        }

        private void MoveFigureRight(object sender, EventArgs e)
        {
            if (!Validation.IsOnRight(field, figureList) && !Validation.IsOnFinishedListRightSideMoving(figureList, finishedList))
            {
                figure.MoveFigureRight();
            }
        }

        private void MoveFigureDown(object sender, EventArgs e)
        {
            if (!Validation.IsOnDown(field, figureList))
            {
                figure.MoveFigureDown();
            }
        }

        private void RotateFigure(object sender, EventArgs e)
        {
            if (Validation.isRotateAvailable(currentFigure, figure, field))
            {
                figure.FigureRotate();
            }
        }
               
        public void DeletingCompleteLines(List<int> coordYCompleteLine)
        {
            for (int i = 0; i < finishedList.Count; i++)
            {
                for (int j = 0; j < coordYCompleteLine.Count; j++)
                {
                    if (finishedList[i].YNode == coordYCompleteLine[j])
                    {
                        finishedList.Remove(finishedList[i]);
                        if (i!=0)
                        {
                            --i;
                        }
                        
                    }
                }
            }
        }

        public void CheckForPointAmount(int lines)
        {
            if (lines == 1)
            {
                currentPoints = 100;
            }
            else if (lines == 2)
            {
                currentPoints = 300;
            }
            else if (lines == 3)
            {
                currentPoints = 700;
            }
            else
            {
                currentPoints = 1500;
            }
        }

        public void MoveLogic()
        {
            figureList = NextFigureGeneration();

            do
            {
                if (Console.KeyAvailable)
                {
                    key = Console.ReadKey(true);
                }
                
                if (key.Key == ConsoleKey.LeftArrow || key.Key == ConsoleKey.RightArrow || key.Key == ConsoleKey.UpArrow)
                {
                    hd.Control(key);
                    for (int i = 0; i < figureList.Count; i++)
                    {
                        drw.DrawNode(figureList[i]);
                    }
                    System.Threading.Thread.Sleep(speed);
                    foreach (var item in figureList)
                    {
                        drw.ClearNode(item);
                    }
                }
               
                if (!Validation.IsOnDown(field, figureList) && !Validation.IsOnFinishedList(figureList, finishedList))
                {
                    foreach (var item in figureList)
                    {
                        item.MoveDown();
                    }
                }

                for (int i = 0; i < figureList.Count; i++)
                {
                    drw.DrawNode(figureList[i]);
                }

                System.Threading.Thread.Sleep(speed);

                foreach (var item in figureList)
                {
                    drw.ClearNode(item);
                }

                key = default(ConsoleKeyInfo);

                if (Validation.IsOnDown(field, figureList) || Validation.IsOnFinishedList(figureList, finishedList))
                {

                    for (int i = 0; i < figureList.Count; i++)
                    {
                        finishedList.Add(figureList[i]);
                    }
                    figureList.Clear();
                    figureList = NextFigureGeneration();
                    if ((completeLines = Validation.IsLineComplete(finishedList, field)) > 0)
                    {
                        
                        coordYCompleteLine = Validation.CoordYCompleteLine(finishedList, field);
                        foreach (var element in finishedList)
                        {
                            drw.ClearNode(element);
                        }
                        DeletingCompleteLines(coordYCompleteLine);
                        coordYCompleteLine.Sort();
                        for (int j = 0; j < coordYCompleteLine.Count; j++)
                        {
                            foreach (var item in finishedList)
                            {
                                if (item.YNode < coordYCompleteLine[j])
                                {
                                    item.MoveDown();
                                }
                            }
                        }
                        CheckForPointAmount(completeLines);
                        score += currentPoints;
                        drw.DrawTheScore(field, currentPoints, score);
                    }
                }


                foreach (var element in finishedList)
                {
                    drw.DrawNode(element);
                }
            } while (true);
        }


    }
}
